package com.study.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.study.exception.ServiceException;
import com.study.mapper.MemeFilesMapper;
import com.study.mapper.MemoMapper;
import com.study.mapper.MemoTagRelationMapper;
import com.study.mapper.TagMapper;
import com.study.model.dto.CreateMemoDto;
import com.study.model.dto.CreateMemoRespDto;
import com.study.model.dto.UpdateMemoDto;
import com.study.model.dto.response.DailyMemoCountRespDto;
import com.study.model.entity.Memo;
import com.study.model.entity.MemoFiles;
import com.study.model.entity.MemoTagRelation;
import com.study.model.entity.Tag;
import com.study.service.MemoService;
import com.study.util.QiniuUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MemoServiceImpl implements MemoService {

    @Autowired
    private MemoMapper memoMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private MemoTagRelationMapper memoTagRelationMapper;

    @Autowired
    private MemeFilesMapper memoFilesMapper;

    @Autowired
    private QiniuUtil qiniuUtil;

    @Override
    @Transactional
    public CreateMemoRespDto createNewMemo(CreateMemoDto createMemoDto) {
        Memo memo = Memo.from(createMemoDto);

        if (StringUtils.isNoneEmpty(createMemoDto.getParentId())) {
            Memo parentMemo = memoMapper.selectById(createMemoDto.getParentId());
            if (parentMemo != null) {
                memo.setParentId(parentMemo.getId());
            }
        }
        memoMapper.insert(memo);
        List<String> tagNameList = saveMemoTags(memo, createMemoDto.getContent(), createMemoDto.getUserId());

        MemoFiles[] memoFiles =createMemoDto.getFileIds();
        for (MemoFiles memoFile:memoFiles){
            memoFile.setMemoId(memo.getId());
            memoFilesMapper.insert(memoFile);
            log.info("创建memo文件{}",memoFile);
        }

        log.info("用户{}创建新的memo{}", createMemoDto.getUserId(), createMemoDto.getContent());
        return new CreateMemoRespDto(memo.getContent(), memo.getCreateTime(), memo.getId(), memo.getDevice(), memo.getParentId(), tagNameList);
    }

    @Override
    public List<String> findUserTagNames(String userId) {
        List<Tag> tagList = tagMapper.selectList(new QueryWrapper<Tag>().eq("user_id", userId));
        return tagList.stream().map(tag -> tag.getTag()).collect(Collectors.toList());
    }

    @Override
    public List<Memo> findAllMemo(String userId, String queryTag) {
//        if (StringUtils.isNoneEmpty(queryTag)) {
//            return memoMapper.findMemoByTagName(userId, "#" + queryTag);
//        }
//        List<Memo> memoList = memoMapper.selectList(new QueryWrapper<Memo>().eq("user_id", userId).orderByDesc("id"));
//        return memoList;
        return memoMapper.findMemoByTagName(userId,StringUtils.isNoneEmpty(queryTag)?"#"+queryTag:"");
    }

    @Override
    @Transactional
    public void deleteMemoById(String userId, String memeoId) {
        Memo memo = memoMapper.selectById(memeoId);
        if (memo == null) {
            throw new ServiceException("memo不存在");
        }
        if (!memo.getUserId().equals(userId)) {
            throw new ServiceException("没有权限删除");
        }
        memoMapper.deleteById(memeoId);
        log.info("user{}delete{}", userId, memo.getContent());

        deleteTagByMemoId(memeoId);
        deleteFilesByMemoId(memeoId);

    }

    private void deleteFilesByMemoId(String memeoId) {
        List<MemoFiles> memoFilesList = memoFilesMapper.selectList(new QueryWrapper<MemoFiles>().eq("memo_id", memeoId));
        if (!memoFilesList.isEmpty()){
            List<String> fileKeyList = memoFilesList.stream().map(e -> e.getFileKey()).collect(Collectors.toList());
            qiniuUtil.batchDeleteFile(fileKeyList.stream().toArray(String[]::new));
            log.info("七牛文件删除{}",fileKeyList);

            memoFilesMapper.delete(new QueryWrapper<MemoFiles>().eq("memo_id",memeoId));
            log.info("删除七牛对应文件记录{}",fileKeyList);

        }
    }

    @Override
    public Memo updateMemo(UpdateMemoDto updateMemoDto) {
        Memo memo = memoMapper.findByUserIdAndMemoId(updateMemoDto.getUserId(), updateMemoDto.getMemoId());
        if (memo==null){
            throw  new ServiceException("memo不存在");
        }
        deleteTagByMemoId(updateMemoDto.getMemoId());
        memo.setContent(updateMemoDto.getContent());
        memoMapper.updateById(memo);

        log.info("memo{}已修改",memo.getId());

        saveMemoTag(memo);

        updateMemoFilesBymemo(updateMemoDto);
        return memo;
    }

    private void updateMemoFilesBymemo(UpdateMemoDto updateMemoDto) {
        List<MemoFiles> memoFiles = memoFilesMapper.selectList(new QueryWrapper<MemoFiles>().eq("memo_id", updateMemoDto.getMemoId()));

        List<MemoFiles> currentFiles = Arrays.asList(updateMemoDto.getMemoFiles());
        List<MemoFiles> newFiles = currentFiles.stream().filter(e -> StringUtils.isEmpty(e.getId())).collect(Collectors.toList());
        List<MemoFiles> oldFiles = currentFiles.stream().filter(e -> StringUtils.isNotEmpty(e.getId())).collect(Collectors.toList());

        if (memoFiles.size()!= oldFiles.size()){
            List<MemoFiles> deleteFiles= new ArrayList<>();
            for (MemoFiles oldFile:memoFiles){
                boolean flag =false;
                for (MemoFiles newFile:newFiles ){
                    if (oldFile.getId().equals(newFile.getId())){
                        flag=true;
                        break;
                    }
                }
                if (flag==false){
                    deleteFiles.add(oldFile);
                }
            }

            List<String> deleteIdList = deleteFiles.stream().map(e -> e.getId()).collect(Collectors.toList());
            memoFilesMapper.deleteBatchIds(deleteIdList);

            qiniuUtil.batchDeleteFile(deleteFiles.stream().map(e -> e.getFileKey()).collect(Collectors.toList()).stream().toArray(String[]::new));

            log.info("修改Memo{},新增文件{}",updateMemoDto.getMemoId(),deleteFiles);
        }

        if (!newFiles.isEmpty()){
            for (MemoFiles newFile:newFiles){
                newFile.setMemoId(updateMemoDto.getMemoId());
                memoFilesMapper.insert(newFile);
            }
            log.info("修改Memo{},删除文件{}",updateMemoDto.getMemoId(),newFiles);
        }
    }

    @Override
    public DailyMemoCountRespDto dailyMemoCount(String userId) {
        List<Map> list = memoMapper.findDailyCount(userId);
        DailyMemoCountRespDto dailyMemoCountRespDto = new DailyMemoCountRespDto();
        dailyMemoCountRespDto.setDailyCount(list);
        return dailyMemoCountRespDto;
    }

    public void deleteTagByMemoId(String memoId) {
        List<MemoTagRelation> memoTagRelations = memoTagRelationMapper.selectList(new QueryWrapper<MemoTagRelation>().eq("memo_id", memoId));
        for (MemoTagRelation memoTagRelation : memoTagRelations) {
            List<MemoTagRelation> tagRelations = memoTagRelationMapper.selectList(new QueryWrapper<MemoTagRelation>().eq("tag_id", memoTagRelation.getTagId()).ne("memo_id", memoId));
            if (tagRelations.isEmpty()) {
                tagMapper.deleteById(memoTagRelation.getTagId());
                log.info("级联删除无效的tag{}", memoTagRelation.getTagId());
            }
            memoTagRelationMapper.deleteById(memoTagRelation.getId());
            log.info("删除无效的tagMemoRelation{}");
        }
    }

    private List<String>  saveMemoTag(Memo memo) {
        String text = Jsoup.parse(memo.getContent()).body().text();
        List<String> tagNameList = extractTagName(text);
        for (String s : tagNameList) {
            Tag tag = new Tag();
            if (tag != null) {
                tag = Tag.from(s, memo.getUserId());
                tagMapper.insert(tag);
            }
            MemoTagRelation memoTagRelation = new MemoTagRelation();
            memoTagRelation.setTagId(tag.getId());
            memoTagRelation.setMemoId(memo.getId());
            memoTagRelationMapper.insert(memoTagRelation);
            log.info("新增memoTag{}", tag);
        }
        return tagNameList;
    }


    private List<String> saveMemoTags(Memo memo, String content, String  userId) {
        String text = Jsoup.parse(content).body().text();
        List<String> tagNameList = extractTagName(text);
        for (String s : tagNameList) {
            Tag tag = new Tag();
            if (tag != null) {
                tag = Tag.from(s, userId);
                tagMapper.insert(tag);
            }
            MemoTagRelation memoTagRelation = new MemoTagRelation();
            memoTagRelation.setTagId(tag.getId());
            memoTagRelation.setMemoId(memo.getId());
            memoTagRelationMapper.insert(memoTagRelation);
            log.info("新增memoTag{}", tag);
        }
        return tagNameList;
    }

    private List<String> extractTagName(String memo) {
        Matcher matcher = Pattern.compile("#(\\w|[^\\-\\xff]|/|\\\\)+(\\s)?", Pattern.DOTALL).matcher(memo);
        List<String> tagNameList = new LinkedList<>();
        while (matcher.find()) {
            String tag = matcher.group().replace("", "");
            tagNameList.add(tag);
        }
        return tagNameList;
    }


}
